﻿using System;
using System.Collections.Generic;
using XCI.Sys.Model;
using XCI.Core;
using XCI.Windows.Extensions;
using XCI.Extensions;
using System.Linq;

namespace XCI.Sys.Service
{
    /// <summary>
    /// 系统字典服务
    /// </summary>
    public class DicService : BaseService<SysDic>
    {
        protected static readonly Dictionary<string, List<SysDic>> DicListCache = new Dictionary<string, List<SysDic>>();
        protected static readonly Dictionary<string, SMap> DicNameCache = new Dictionary<string, SMap>();
        public static readonly DicService Instance = new DicService();
        protected override string RootUrl => "/api/sys/dic/";

        /// <summary>
        /// 新建字典模型
        /// </summary>
        public SysDic New()
        {
            return new SysDic
            {
                Id = NewId(),
                Status = true
            };
        }

        /// <summary>
        /// 复制字典模型
        /// </summary>
        /// <param name="original">原模型</param>
        public SysDic Copy(SysDic original)
        {
            if (original == null) throw new ArgumentNullException(nameof(original));
            var model = original?.Clone();
            model.Id = NewId();
            return model;
        }

        /// <summary>
        /// 检查字典编码是否存在
        /// </summary>
        /// <param name="code">字典编码</param>
        public bool ExistByCode(string code)
        {
            return ExistByCodeCore(code);
        }

        /// <summary>
        /// 新建字典
        /// </summary>
        /// <param name="model">字典模型对象</param>
        /// <returns>成功返回true</returns>
        public bool Insert(SysDic model)
        {
            return InsertCore(model);
        }

        /// <summary>
        /// 修改字典
        /// </summary>
        /// <param name="model">字典模型对象</param>
        /// <returns>成功返回true</returns>
        public bool Update(SysDic model)
        {
            return UpdateCore(model);
        }

        /// <summary>
        /// 删除字典
        /// </summary>
        /// <param name="ids">主键字符串</param>
        /// <returns>成功返回true</returns>
        public bool Delete(string ids)
        {
            return DeleteByIdsCore(ids);
        }

        /// <summary>
        /// 根据字典类型编码删除
        /// </summary>
        /// <param name="code">字典类型编码</param>
        /// <returns>成功返回true</returns>
        public bool DeleteByCode(string code)
        {
            var url = GetUrl("deleteByCode", code);
            return SysRuntime.Api.PostAsMessage(url).EnsureSuccess().Success;
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="ids">主键字符串</param>
        /// <param name="status">状态,1启用;0禁用</param>
        /// <returns>成功返回true</returns>
        public bool UpdateStatus(string ids, bool status)
        {
            return UpdateStatusByIdsCore(ids, status);
        }

        /// <summary>
        /// 根据主键获取字典对象
        /// </summary>
        /// <param name="id">字典主键</param>
        public SysDic SelectById(string id)
        {
            return SelectByIdCore(id);
        }

        /// <summary>
        /// 根据类型编码查询字典数量
        /// </summary>
        /// <param name="code">字典类型编码</param>
        public int SelectCountByCode(string code)
        {
            var url = GetUrl("selectCountByCode", code);
            return SysRuntime.Api.Post<int>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 根据字典编码获取字典对象
        /// </summary>
        /// <param name="code">字典编码</param>
        /// <returns>成功返回模型对象</returns>
        public List<SysDic> SelectListByCode(string code)
        {
            var url = GetUrl("selectListByCode", code);
            return SysRuntime.Api.Post<List<SysDic>>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 查询字典分页列表
        /// </summary>
        /// <param name="paged">分页参数</param>
        /// <param name="code">字典类型编码</param>
        /// <param name="key">名称/简拼关键字</param>
        /// <param name="status">状态(false:禁用;true:启用;null:全部记录)</param>
        public PageList<SysDic> SelectPageList(PageParam paged, string code, string key, bool? status)
        {
            var map = GetQueryMap(ToPageMap(paged), code, key, status);
            return SelectPageListCore(map);
        }

        /// <summary>
        /// 查询字典列表
        /// </summary>
        /// <param name="code">字典类型编码</param>
        /// <param name="key">名称/简拼关键字</param>
        /// <param name="status">状态(false:禁用;true:启用;null:全部记录)</param>
        public List<SysDic> SelectList(string code, string key, bool? status)
        {
            var map = GetQueryMap(Map.New, code, key, status);
            return SelectListCore(map);
        }

        /// <summary>
        /// 刷新字典缓存
        /// </summary>
        public void RefreshDicListCache()
        {
            var list = SelectList(null, null, true);
            DicListCache.Clear();
            DicNameCache.Clear();
            foreach (var item in list)
            {
                if (item.Code.IsEmpty()) continue;

                if (DicListCache.TryGetValue(item.Code, out List<SysDic> val))
                {
                    val.Add(item);
                }
                else
                {
                    var vlist = new List<SysDic>();
                    vlist.Add(item);
                    DicListCache.Add(item.Code, vlist);
                }

                if (item.Value.IsEmpty()) continue;
                if (DicNameCache.TryGetValue(item.Code, out SMap smap))
                {
                    smap[item.Value] = item.Name;
                }
                else
                {
                    DicNameCache.Add(item.Code, SMap.New.Add(item.Value, item.Name));
                }
            }
        }

        /// <summary>
        /// 在缓存中查询字典列表
        /// </summary>
        /// <param name="code">字典类型编码</param>
        public List<SysDic> GetDicListByCache(string code)
        {
            if (DicListCache.TryGetValue(code, out List<SysDic> val))
            {
                return val.ToList();
            }
            return new List<SysDic>();
        }

        /// <summary>
        /// 在缓存中查询字典列表
        /// </summary>
        /// <param name="code">字典类型编码</param>
        /// <param name="value">字典值</param>
        /// <param name="defaultName">找不到指定的项值时返回的默认名称</param>
        public string GetDicNameByCacheValue(string code, string value, string defaultName = SysConst.Empty)
        {
            if (code.IsEmpty()) throw new ArgumentNullException("code", "字典类型编码");
            if (value.IsEmpty()) return defaultName;

            var result = string.Empty;
            if (DicNameCache.TryGetValue(code, out SMap smap) && smap.TryGetValue(value, out string name) && name.IsNotEmpty())
            {
                result = name;
            }

            return result.IsEmpty() ? defaultName : result;
        }

        ///// <summary>
        ///// 查询所有字典列表
        ///// </summary>
        //public List<SysDic> SelectAllList()
        //{
        //    var url = GetUrl("selectAllList");
        //    return SysRuntime.Api.Post<List<SysDic>>(url).EnsureSuccess().Data;
        //}

        ///// <summary>
        ///// 查询所有数据字典键值对
        ///// </summary>
        //public Dictionary<string, SMap> SelectAllMap()
        //{
        //    var url = GetUrl("selectAllMap");
        //    return SysRuntime.Api.Post<Dictionary<string, SMap>>(url).EnsureSuccess().Data;
        //}



        /// <summary>
        /// 导出字典列表
        /// </summary>
        /// <param name="code">字典类型编码</param>
        /// <param name="key">名称/简拼关键字</param>
        /// <param name="status">状态(false:禁用;true:启用;null:全部记录)</param>
        public byte[] Export(string code, string key, bool? status)
        {
            var map = GetQueryMap(Map.New, code, key, status);
            return ExportCore(map);
        }

        /// <summary>
        /// 刷新服务端字典缓存
        /// </summary>
        public bool RefreshCache()
        {
            return RefreshCacheCore();
        }

        private Map GetQueryMap(Map map, string code, string key, bool? status)
        {
            return map
                .Add("code", code)
                .Add("key", key)
                .Add("status", status);
        }
    }
}